import { computed, Ref, set } from 'vue'
import { Widget } from '@/models'
import { TableDefault, TableField, TableItem } from '@/types'
import config from '@/config'
import { createId } from '@/utils'

/** 获取表格值 */
export function getTableValue(widget: Widget) {
  const fields = widget.tableFields

  return widget.tableData.map(item =>
    fields.reduce((data, field) => {
      data.push((item[field.id || ''] as string) || '')
      return data
    }, <string[]>[])
  )
}

/** 表格填写校验 */
export function tableValidate(widget: Widget): {
  /** 是否整个表格错误 */
  full: boolean
  /** 错误消息 */
  error: string
} | void {
  const {
    required,
    tableFields: fields,
    tableOptions: options,
    tableValue: value,
    tableData: data,
    isHorizontalTable: isHorizontal
  } = widget

  // 必填校验
  if (required && !widget.hasFillValue)
    return {
      full: true,
      error: `请填写${widget.displayName}`
    }

  /** 已填写数据项 */
  const filledItem = data.filter((item, index) => !!value[index]?.join(''))

  const { requiredCount } = options

  // 必填项数校验
  if (required && requiredCount && filledItem.length < requiredCount) {
    return {
      full: true,
      error: `请至少填写${requiredCount}${isHorizontal ? '行' : '列'}`
    }
  }

  /** 必填字段项 */
  const requiredFields = fields.filter(field => field.required)

  /** 错误的字段 */
  let invalidField = <TableField | undefined>undefined

  /** 字段未完成必填 */
  const invalidItem = filledItem.find(item =>
    requiredFields.some(field => {
      if (!item[field.id || '']) {
        invalidField = field
        return true
      }
    })
  )

  // 校验必填字段
  if (invalidItem) {
    const label = invalidField?.label || ''
    return {
      full: false,
      error: `请填写${label ? `“${label}”` : ''}必填字段`
    }
  }
}

/** 获取表格控件列宽 */
export function getTableColWidths(widget: Widget) {
  const { colWidthDefault } = TableDefault

  if (widget.isHorizontalTable) {
    // 横向表格，取字段配置的宽度
    return widget.tableFields.map(item => item.width || colWidthDefault)
  } else {
    // 纵向表格，取数据存储的宽度
    const widths = widget.tableData.map(item => item.width || colWidthDefault)

    const { headerHidden, headerWidth } = widget.tableOptions

    // 不隐藏表头则追加头部宽度
    if (!headerHidden) {
      widths.unshift(headerWidth)
    }

    return widths
  }
}

/** 设置表格控件列宽 */
export function setTableColWidth(widget: Widget, index: number, width: number) {
  if (widget.isHorizontalTable) {
    // 横向表格，设置字段配置的宽度
    const field = widget.tableFields[index]

    if (field) field.width = width
  } else {
    const { headerHidden } = widget.tableOptions

    // 隐藏表头
    if (headerHidden) {
      const item = widget.tableData[index]
      // 更新数据中记录的宽度
      if (item) item.width = width
    } else {
      // 表头列宽
      if (index === 0) {
        widget.tableOptions.headerWidth = width
      } else {
        const item = widget.tableData[index - 1]
        // 更新数据中记录的宽度
        if (item) item.width = width
      }
    }
  }
}

/** 设置表格控件列宽 */
export function setTableColWidths(widget: Widget, widths: number[]) {
  for (let i = 0, l = widths.length; i < l; i++) {
    setTableColWidth(widget, i, widths[i])
  }
}

/** 表格数据行数，不含表头 */
export function getTableRows(widget: Widget) {
  return widget.isHorizontalTable ? widget.tableData.length : widget.tableFields.length
}

/** 设置表格数据行数 */
export function setTableRows(widget: Widget, length: number) {
  widget.tableOptions.rows = length

  if (widget.isHorizontalTable) {
    updateTableDataLength(widget, length)
  } else {
    updateTableFieldsLength(widget, length)
  }
}

/** 表格数据最大行数 */
export function getTableRowsMax(widget: Widget) {
  const leftRows = Math.max(Math.floor((widget.page.h - widget.y - widget.h) / widget.tableOptions.rowHeight), 0)

  return Math.min(config.tableOption.rowsMax, leftRows + widget.tableRows)
}

/** 表格数据最大行高 */
export function getTableRowsHeightMax(widget: Widget) {
  const { headerHidden, headerHeight } = widget.tableOptions
  const { rowHeightMax, rowHeightMin } = config.tableOption

  const leftH = widget.page.h - widget.y - (widget.isHorizontalTable && !headerHidden ? headerHeight : 0)

  return Math.max(Math.min(rowHeightMax, Math.floor(leftH / widget.tableRows - 1)), rowHeightMin)
}

/** 表格数据列数，不含表头 */
export function getTableCols(widget: Widget) {
  return widget.isHorizontalTable ? widget.tableFields.length : widget.tableData.length
}

/** 设置时表格数据列数 */
export function setTableCols(widget: Widget, length: number) {
  widget.tableOptions.cols = length

  if (widget.isHorizontalTable) {
    updateTableFieldsLength(widget, length)
  } else {
    updateTableDataLength(widget, length)
  }
}

/** 表格数据最大列数 */
export function getTableColsMax(widget: Widget) {
  const leftCols = Math.max(Math.floor((widget.page.w - widget.x - widget.w) / TableDefault.colWidthDefault), 0)

  return Math.min(config.tableOption.colsMax, leftCols + widget.tableCols)
}

/** 添加表格字段 */
export function addTableField(widget: Widget, index?: number, field?: TableField) {
  const { tableFields: fields } = widget
  const length = fields.length

  /** 补充字段信息 */
  field = {
    label: `表头${length + 1}`,

    placeholder: '',

    required: false,

    id: createId(),

    width: TableDefault.colWidthDefault,

    ...field
  }

  if (index !== undefined && index > -1 && index < length) {
    fields.splice(index, 0, field)
    widget.extra.activeFieldIndex = index
  } else {
    fields.push(field)
    widget.extra.activeFieldIndex = length
  }
}

/** 移除表格字段 */
export function removeTableField(widget: Widget, index: number) {
  widget.tableFields.splice(index, 1)
}

/** 通过设置长度更新字段列表 */
export function updateTableFieldsLength(widget: Widget, length: number) {
  const { length: exist } = widget.tableFields

  if (length > exist) {
    // 如果数量超过则增加表格项
    for (let i = exist; i < length; i++) {
      addTableField(widget)
    }
  } else if (length < exist) {
    // 如果数量少于则删除表格项
    for (let i = exist; i > length; i--) {
      removeTableField(widget, i - 1)
    }
  }
}

/** 添加表格数据项 */
export function addTableData(widget: Widget, index?: number, item?: TableItem) {
  const { tableData: items } = widget
  const length = items.length

  /** 补充字段信息 */
  item = {
    width: TableDefault.colWidthDefault,
    ...item
  }

  if (!item) return

  if (index !== undefined && index > -1 && index < length) {
    items.splice(index, 0, item)
  } else {
    items.push(item)
  }
}

/** 移除表格数据项 */
export function removeTableData(widget: Widget, index: number) {
  widget.tableData.splice(index, 1)
}

/** 通过设置长度更新数据列表 */
export function updateTableDataLength(widget: Widget, length: number) {
  const { length: exist } = widget.tableData

  if (length > exist) {
    // 如果数量超过则增加表格项
    for (let i = exist; i < length; i++) {
      addTableData(widget)
    }
  } else if (length < exist) {
    // 如果数量少于则删除表格项
    for (let i = exist; i > length; i--) {
      removeTableData(widget, i - 1)
    }
  }
}

/** 表格尺寸 */
export function getTableSize(widget: Widget) {
  const options = widget.tableOptions

  const w = widget.tableColWidths.reduce((total, w) => total + w, 0)

  const h =
    widget.tableRows * (options.rowHeight + 1) +
    (!widget.isVerticalTable && !options.headerHidden ? options.headerHeight : 0)

  return { w, h }
}

/** 表格是否超出页面 */
export function isTableOutOfPage(widget: Widget) {
  const {
    tableSize: { w, h },
    page: { w: pw, h: ph }
  } = widget

  return w > pw || h > ph
}

/**
 * 表格自动裁剪，用于超出页面范围时删除超出的行列
 * adjust 为 `true` 会尝试更改行高和列宽为默认
 */
export function tableAutoCrop(widget: Widget, adjust = true) {
  const {
    tableOptions: options,
    tableSize: { w, h },
    page: { w: pw, h: ph },
    isHorizontalTable: horizontal
  } = widget

  const isWidthOut = w > pw
  const isHeightOut = h > ph

  if (!isWidthOut && !isHeightOut) return

  const { colWidthDefault } = TableDefault

  // 宽度超出
  if (isWidthOut) {
    // 尝试修改较大列宽为默认列宽
    if (adjust) widget.tableColWidths = widget.tableColWidths.map(w => Math.min(colWidthDefault, w))

    const data = horizontal ? widget.tableFields : widget.tableData

    for (let i = data.length - 1; i > 0; i--) {
      if (widget.tableSize.w > pw) {
        data.splice(i, 1)
      } else {
        break
      }
    }
  }

  // 高度超出
  if (isHeightOut) {
    // 尝试修改较大列宽为默认列宽
    if (adjust) options.rowHeight = Math.min(options.rowHeight, TableDefault.rowHeight)

    const data = horizontal ? widget.tableData : widget.tableFields

    for (let i = data.length - 1; i > 0; i--) {
      if (widget.tableSize.h > ph) {
        data.splice(i, 1)
      } else {
        break
      }
    }
  }
}

/** 表格字段激活 */
export function useFieldActiveIndex(data: Ref<Widget>) {
  return computed({
    get: () => (data.value.extra.activeFieldIndex || 0) as number | undefined,
    set: val => set(data.value.extra, 'activeFieldIndex', val)
  })
}
